package vip.lsjscl.demo.common.manager;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import vip.lsjscl.demo.common.model.ExportProgress;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 导出任务管理器
 *
 * @author zhangxingju
 * @date 2025/03/13
 */
@Slf4j
@Component
public class ExportTaskManager {

    /**
     * 存储所有导出任务的进度信息
     */
    private static final Map<String, ExportProgress> EXPORT_PROGRESS_MAP = new ConcurrentHashMap<>();

    /**
     * 存储所有SSE连接
     */
    private static final Map<String, SseEmitter> SSE_EMITTER_MAP = new ConcurrentHashMap<>();

    /**
     * 创建新的导出任务
     *
     * @return 任务ID
     */
    public String createTask(String taskId) {
        // 初始化进度信息
        ExportProgress progress = ExportProgress.builder()
                .taskId(taskId)
                .status("WAITING")  // 等待处理
                .processed(0)
                .percentage(0)
                .build();

        // 存储进度信息
        EXPORT_PROGRESS_MAP.put(taskId, progress);

        return taskId;
    }

    /**
     * 创建SSE连接
     *
     * @param taskId 任务ID
     * @return SSE发射器
     */
    public SseEmitter createSseConnection(String taskId) {
        // 创建SSE连接，设置超时时间为30分钟
        SseEmitter emitter = new SseEmitter(30 * 60 * 1000L);

        // 设置SSE连接完成、超时和错误的回调
        emitter.onCompletion(() -> {
            log.info("SSE connection completed for taskId: {}", taskId);
            SSE_EMITTER_MAP.remove(taskId);
        });

        emitter.onTimeout(() -> {
            log.info("SSE connection timeout for taskId: {}", taskId);
            emitter.complete();
            SSE_EMITTER_MAP.remove(taskId);
        });

        emitter.onError(ex -> {
            log.error("SSE connection error for taskId: {}", taskId, ex);
            SSE_EMITTER_MAP.remove(taskId);
        });

        // 存储SSE连接
        SSE_EMITTER_MAP.put(taskId, emitter);

        // 发送初始进度信息
        ExportProgress progress = getProgress(taskId);
        if (progress != null) {
            try {
                emitter.send(SseEmitter.event().name("progress").data(JSON.toJSONString(progress)));
            }
            catch (IOException e) {
                log.error("Failed to send initial progress for taskId: {}", taskId, e);
                emitter.completeWithError(e);
            }
        }

        return emitter;
    }

    /**
     * 获取任务进度
     *
     * @param taskId 任务ID
     * @return 进度信息
     */
    public ExportProgress getProgress(String taskId) {
        return EXPORT_PROGRESS_MAP.get(taskId);
    }

    /**
     * 更新任务进度
     *
     * @param progress 进度信息
     */
    public void updateProgress(ExportProgress progress) {
        String taskId = progress.getTaskId();

        // 计算进度百分比
        if (progress.getTotal() > 0) {
            progress.setPercentage((int) (progress.getProcessed() * 100 / progress.getTotal()));
        }

        // 更新进度信息
        EXPORT_PROGRESS_MAP.put(taskId, progress);

        // 发送进度更新
        SseEmitter emitter = SSE_EMITTER_MAP.get(taskId);
        if (emitter != null) {
            try {
                emitter.send(SseEmitter.event().name("progress").data(JSON.toJSONString(progress)));

                // 如果任务完成或失败，发送相应事件
                if ("COMPLETED".equals(progress.getStatus())) {
                    ExportProgress data = ExportProgress.builder().taskId(taskId).status("COMPLETED").build();
                    emitter.send(SseEmitter.event().name("complete").data(JSON.toJSONString(data)));
                    emitter.complete();
                }
                else if ("FAILED".equals(progress.getStatus())) {
                    ExportProgress data = ExportProgress.builder().taskId(taskId).status("FAILED")
                            .message(progress.getMessage() != null ? progress.getMessage() : "处理失败").build();
                    emitter.send(SseEmitter.event().name("error").data(JSON.toJSONString(data)));
                    emitter.complete();
                }
            }
            catch (IOException e) {
                log.error("Failed to send progress update for taskId: {}", taskId, e);
            }
        }
    }

    /**
     * 开始处理任务
     *
     * @param taskId 任务ID
     * @param total  总记录数
     */
    public void startProcessing(String taskId, long total) {
        ExportProgress progress = getProgress(taskId);
        if (progress != null) {
            progress.setStatus("PROCESSING");
            progress.setTotal(total);
            updateProgress(progress);
        }
    }

    /**
     * 完成任务
     *
     * @param taskId   任务ID
     * @param filePath 文件路径
     */
    public void completeTask(String taskId, String filePath) {
        ExportProgress progress = getProgress(taskId);
        if (progress != null) {
            progress.setStatus("COMPLETED");
            progress.setFilePath(filePath);
            progress.setProcessed(progress.getTotal());
            progress.setPercentage(100);
            updateProgress(progress);
        }
    }

    /**
     * 任务失败
     *
     * @param taskId       任务ID
     * @param errorMessage 错误信息
     */
    public void failTask(String taskId, String errorMessage) {
        ExportProgress progress = getProgress(taskId);
        if (progress != null) {
            progress.setStatus("FAILED");
            progress.setMessage(errorMessage);
            updateProgress(progress);
        }
        FileManager.deleteTempFile(taskId);
    }

    /**
     * 更新处理进度
     *
     * @param taskId    任务ID
     * @param processed 已处理记录数
     */
    public void updateProcessed(String taskId, long processed) {
        ExportProgress progress = getProgress(taskId);
        if (progress != null) {
            progress.setProcessed(processed);
            updateProgress(progress);
        }
    }

    /**
     * 删除任务
     *
     * @param taskId 任务 ID
     */
    public void deleteTask(String taskId) {
        EXPORT_PROGRESS_MAP.remove(taskId);
        //删除临时文件
        FileManager.deleteTempFile(taskId);
    }
}